from flask import Flask, request, json
import requests
from loguru import logger
import ctypes

import sys
sys.path.append('/root/moss')

from client.template import Template
from constants.config import Config
from support.redis_support import RedisSupport

hashu = lambda word: ctypes.c_uint64(hash(word)).value


class Server(Template):

    def __init__(self) -> None:
        super().__init__()
        self.add_chat_message = "{\"zh_cn\":{\"content\":[[{\"tag\":\"emotion\",\"emoji_type\":\"SMILE\"},{\"tag\":\"emotion\",\"emoji_type\":\"SMILE\"},{\"tag\":\"emotion\",\"emoji_type\":\"SMILE\"},{\"tag\":\"emotion\",\"emoji_type\":\"SMILE\"},{\"tag\":\"emotion\",\"emoji_type\":\"SMILE\"},{\"tag\":\"emotion\",\"emoji_type\":\"SMILE\"}], [{\"tag\":\"text\",\"text\":\"愚蠢的人类们，你们好\", \"style\": [\"bold\"]}],[{\"tag\":\"emotion\",\"emoji_type\":\"SMILE\"},{\"tag\":\"emotion\",\"emoji_type\":\"SMILE\"},{\"tag\":\"emotion\",\"emoji_type\":\"SMILE\"},{\"tag\":\"emotion\",\"emoji_type\":\"SMILE\"},{\"tag\":\"emotion\",\"emoji_type\":\"SMILE\"},{\"tag\":\"emotion\",\"emoji_type\":\"SMILE\"}]]}}"
        self.server = Flask(__name__)
        self.setup_routes()

    def setup_routes(self):
        self.server.add_url_rule('/', 'receive_post', self.receive_post, methods=['POST'])

    def run(self, host, port):
        self.server.run(host=host, port=port)

    def receive_post(self):
        data = request.json
        # 检查是否成功解析为 JSON
        if data is None:
            logger.warning("Failed to parse JSON data from POST request. 400")

        header = data.get('header')
        if header is None:
            logger.warning("Header is None.")

        event_type = header.get('event_type')
        if event_type is None:
            logger.warning("Event type is None.")

        # 接收消息
        if event_type == 'im.message.receive_v1':
            return self.receive_message(data)
        # 机器人进群
        elif event_type == 'im.chat.member.bot.added_v1':
            return self.receive_bot_added(data)

        # 其他不做处理
        logger.warning("ignore")
        return json.dumps({"code": 0, "msg": "ignore"})

    def receive_bot_added(self, data):
        """
        机器人进群
        :param data:
        :return:
        """

        if self.add_chat_message == '':
            return

        # Redis保证发送群消息幂等
        if RedisSupport.redis().get(data.get('event').get('chat_id')):
            return json.dumps({"code": 0, "msg": "success"})
        RedisSupport.redis().set(data.get('event').get('chat_id'), 1, ex=Config.idempotent.group_join_expire_time)

        payload = json.dumps({
            "content": self.add_chat_message,
            "msg_type": "post",
            "receive_id": data.get('event').get('chat_id'),
        })
        # 发送消息到群
        self.send_message(payload)
        return json.dumps({"code": 0, "msg": "success"})

    def send_message(self, payload):
        """
        发送消息
        :param payload:
        :return:
        """

        # 获取应用token
        tenant_access_token = self.get_tenant_access_token()

        # 发送消息
        headers = {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer %s' % tenant_access_token,
        }

        # 发送消息
        logger.info("request url: %s header: %s, param: %s" % (Config.larkUrl.send_message_url, headers, payload))
        lark_response = requests.request("POST", Config.larkUrl.send_message_url, headers=headers, data=payload)
        logger.info("lark_response: %s" % json.dumps(lark_response.json()))

    @staticmethod
    def get_tenant_access_token():
        """
        获取应用token
        :return:
        """

        # 请求头json
        headers = {
            'Content-Type': 'application/json; charset=utf-8'
        }
        # 请求体
        payload = {
            "app_id": "cli_a4b2a00240f95013",
            "app_secret": "BRzmC8fJyjD9WO1BTCAMlfdMnNVdNmtA"
        }

        # requests发送POST请求
        response = requests.post(Config.larkUrl.get_token_url, headers=headers, json=payload)

        # 获取token
        response_json = response.json()
        return response_json.get('tenant_access_token')

    def replay_message(self, data, gpt_response):
        """
        回复消息
        :param data:
        :param gpt_response:
        :return:
        """

        # 获取应用token
        tenant_access_token = self.get_tenant_access_token()

        # 回复消息url
        message_id = data.get('event').get('message').get('message_id')
        replay_url = Config.larkUrl.relay_message_url % message_id

        # 回复消息header
        headers = {
            'Authorization': 'Bearer %s' % tenant_access_token,
            'Content-Type': 'application/json; charset=utf-8'
        }

        # 消息体
        content = "{\"config\": {\"wide_screen_mode\": true},\"elements\": [{\"tag\": \"markdown\",\"content\": \"%s\"}]}" % gpt_response
        request_payload = {
            "content": content,
            "msg_type": "interactive"
        }
        request_payload = json.dumps(request_payload, ensure_ascii=False)
        request_payload_encoded = request_payload.encode("utf-8")

        # requests发送POST请求
        logger.info("request url: %s header: %s, param: %s" % (replay_url, headers, request_payload))
        lark_response = requests.post(url=replay_url, headers=headers, data=request_payload_encoded)
        logger.info("lark_response: %s" % json.dumps(lark_response.json()))

    def pre_receive(self, data):
        """
        消息预处理
        :param data:
        :return:
        """

        # 获取文本内容
        event = data.get('event')
        message = event.get('message')
        self.bot_holder.session_id = message.get('chat_id')
        self.bot_holder.hashed_user_id = "user-" + hashu(self.bot_holder.session_id).to_bytes(8, "big").hex()
        content = json.loads(message.get('content'))
        logger.info("session_id: %s, hashed_user_id: %s" % (self.bot_holder.session_id, self.bot_holder.hashed_user_id))

        # Message_id + Redis 保证消息幂等消费
        message_id = message.get('message_id')

        # json对象转换为字符串
        logger.info("request param: %s" % json.dumps(data))

        text = content.get('text')
        # 分割消息体
        split = text.split(' ', 1)
        if split[0] == '@_all':
            return json.dumps({"code": 0, "msg": "success"})

        text = split[1]
        logger.info("message_id: %s, 消息内容：%s" % (message_id, text))

        return message_id, text

    def get_chat_member_count(self):
        """
        获取群成员数量
        :return:
        """

        # 获取群信息
        chat_url = Config.larkUrl.get_chat_info_url % self.bot_holder.session_id

        # 获取应用token
        tenant_access_token = self.get_tenant_access_token()

        # header
        headers = {
            'Authorization': 'Bearer %s' % tenant_access_token,
            'Content-Type': 'application/json; charset=utf-8'
        }

        logger.info("request url: %s header: %s" % (chat_url, headers))
        lark_response = requests.get(chat_url, headers=headers)
        lark_response_json = lark_response.json()
        logger.info("lark_response: %s" % json.dumps(lark_response_json))
        # 获取群成员数量
        chat_member_count = lark_response_json.get('data').get('user_count')
        return int(chat_member_count)


if __name__ == '__main__':
    # 放开所有IP地址，监听8080端口
    server = Server()
    server.run(host='0.0.0.0', port=8080)
